package com.zjl.SpringBoot.第21章_流式_响应式_编程.A_前置知识;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 1. Stream关注的是对数据的运算，与CPU打交道
 * 集合关注的是数据的存储，与内存打交道
 * 2.①Stream 自己不会存储元素。
 * ②Stream 不会改变源对象。相反，他们会返回一个持有结果的新Stream。
 * ③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行
 * <p>
 * 3.Stream 执行流程
 * ① Stream的实例化
 * ② 一系列的中间操作（过滤、映射、...)
 * ③ 终止操作
 * 4.说明：
 * 4.1 一个中间操作链，对数据源的数据进行处理
 * 4.2 一旦执行终止操作，就执行中间操作链，并产生结果。之后不能再执行中间操作
 * 之后，不会再被使用测试Stream的实例化
 */
public class C5_StreamAPI的基本方法 {

    private static List<User> List数组() {
        List<User> list = new ArrayList<>();
        list.add(new User(1001, "马化腾", 34));
        list.add(new User(1002, "马云", 12));
        list.add(new User(1003, "刘强东", 33));
        list.add(new User(1004, "雷军", 26));
        list.add(new User(1005, "李彦宏", 65));
        list.add(new User(1006, "比尔盖茨", 42));
        list.add(new User(1007, "任正非", 26));
        list.add(new User(1008, "扎克伯格", 35));

        return list;
    }

    @Test
    public void Stream筛选过滤() {

        List<User> list = List数组();//获取数组
        Stream<User> stream = list.stream();//获取流
        //
        System.out.println("-----filter筛选过滤---------------");
        List<User> collect = stream.
                filter(e -> e.getAge() > 20).//遍历 筛选出年龄大于20的
                        collect(Collectors.toList());//返成List
        //Stream<User>  把这种类型转换成Collectors.toList()指定的类型
        collect.forEach(System.out::println);
        System.out.println("-----filter筛选过滤---------------");
        stream = list.stream();//获取流    流只能操作一次
        List<User> collect2 = stream.
                takeWhile(e -> e.getAge() > 20).//遍历  不满足直接跳出
                        collect(Collectors.toList());//返成List
        collect2.forEach(System.out::println);
    }

    @Test
    public void Stream的Collectors收集方法() {
        List<User> list = List数组();//获取数组
        //
        System.out.println("-----filter筛选过滤---------------");
        Stream<User> stream = list.stream();//获取流
        List<User> collect = stream.filter(e -> e.getAge() > 20).//遍历 筛选出年龄大于20的
                collect(Collectors.toList());//返成List

        collect.forEach(System.out::println);
        System.out.println("-----filter筛选过滤-之Collectors--------------");
        stream = list.stream();//获取流
        Map<Integer, List<User>> collect1 = stream.filter(e -> e.getAge() > 20).//遍历 筛选出年龄大于20的
                collect(Collectors.groupingBy(t -> t.getAge()));//返成Map 对指定分组

        Map<Integer, Map<Integer, List<User>>> collect2 = stream.filter(e -> e.getAge() > 20).//遍历 筛选出年龄大于20的
                collect(Collectors.groupingBy(t -> t.getAge(),
                        Collectors.groupingBy(t -> t.getAge())));//套娃

        collect1.forEach((k,v)->{
            System.out.println(k  + ":" + v);
        });

        System.out.println(Collectors.toList());


    }

    @Test
    public void Stream切片() {

        List<User> list = List数组();//获取数组
        Stream<User> stream = list.stream();//获取流
        //
        stream.skip(2).//跳过前两个
                limit(2).//前两个(由于先跳两个，所以返回第三和第四个)
                //遍历     输出
                        forEach(System.out::println);

    }

    @Test
    public void Stream去重() {

        List<User> list = List数组();//获取数组
        list.add(new User(1008, "扎克伯格", 35));
        list.add(new User(1008, "扎克伯格", 35));
        Stream<User> stream = list.stream();//获取流
        //去重  根据 hashCode  和 equals 方法判断（和Map的判断重复雷同）
        stream.distinct().//去重
                forEach(System.out::println);
    }

    @Test
    public void Stream映射() {

//        map(Function f)——接收一个函数作为参数，将元素转换成其形式或提取信息，
//        该函数会被应用到每个元素上，并将其映射成一个新的元素。
        List<Integer> list1 = Arrays.asList(1, 2, 3);
        list1.stream().map(x -> x * 2)//把每个元素变成原来的2倍
                .forEach(System.out::println);//遍历输出
        //.toArray()//转换成数组
        //.collect(Collectors.toList());//把这个流转成List集合
//        count()//返回元素数量
    }

    @Test
    public void Stream排序() {

        List<Integer> list1 = Arrays.asList(7, 6, 4, 6, 9, 7, 584, 8, 87, 8, 7, 8);
        list1.stream()
                .sorted((o1, o2) -> o2.compareTo(o1))//排序  不影响原来的元素
                //排序  默认自然排序（如果没有实现自然排序接口会报错） ，主动写 ，用写的
                .forEach(System.out::println);//遍历输出
    }

    @Test
    public void Stream获取peek() {

        List<Integer> list1 = Arrays.asList(7, 6, 4, 6, 9, 7, 584, 8, 87, 8, 7, 8);
        list1.stream()
                .sorted((o1, o2) -> o2.compareTo(o1))//排序  不影响原来的元素
                //排序  默认自然排序（如果没有实现自然排序接口会报错） ，主动写 ，用写的
                .peek(k -> {
                    System.out.println(k);
                })
                .toArray();
//                .forEach(System.out::println);//遍历输出
    }

    @Test
    public void Stream的综合() {
        List<User> list = List数组();
        list.stream()/*创建一个顺序流*/
                .filter(t -> t.getId() % 2 == 0)//filter过滤
                .filter(t -> t.getAge() > 24)
                .map(x -> x.getUsername().toUpperCase())//转大写
                .sorted(String::compareTo)//(o1, o2) ->  o2.compareTo(o1)//排序
                .limit(1)//使元素不得超过给定的数量
                .forEach(System.out::println);

        System.out.println("****skip()**跳过多少元素**************************");
        list.stream().skip(7).forEach(System.out::println);//当数字大于数组长度   没有输出
        System.out.println("****distinct()**去重***用equals和hashCode********");
        list.stream().distinct().forEach(System.out::println);//只有完全相同才会一致d

//        map(Function f)——接收一个函数作为参数，将元素转换成其形式或提取信息，该函数会被应用到每个元素上，并将其映射成一个新的元素。
        System.out.println("****map()****映射********");
        List<Integer> list1 = Arrays.asList(1, 2, 3);
        list1.stream().map(x -> x * 2)//把每个元素变成原来的2倍
                .toArray();//转换成数组//collect(Collectors.toList());//把这个流转成List集合
//        count()//返回元素数量
    }


}
